﻿using Servo_Tool.cache;
using Servo_Tool.client;
using Servo_Tool.dal;
using Servo_Tool.entity;
using Servo_Tool.handler;
using Servo_Tool.init;
using Servo_Tool.log;
using Servo_Tool.utils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Servo_UI
{
    public partial class FrmMain : Form
    {
        private readonly Dictionary<string, TextBox> show_dict = new Dictionary<string, TextBox>();
        public FrmMain()
        {
            InitializeComponent();
            InitUI();
        }

        #region ###UI###
        private void InitUI()
        {
            string unitSql = "select * from plc_unit T1 where unit_no='HK_CV' limit 1";
            try
            {
                PlcUnitEntity s7Unit = DBFactory.QueryFirst<PlcUnitEntity>(unitSql);
                if (s7Unit == null)
                {
                    MessageBox.Show("未检测到需要连接的设备!请检测[PLC_UNIT]中相关配置项");
                    Environment.Exit(Environment.ExitCode);
                    Dispose();
                    Close();
                }
                //初始化窗体
                string unitNo = s7Unit.UNIT_NO;
                GlobalCachePool.single_unit_dict.Add(unitNo, s7Unit);
                TabPage page = new TabPage(unitNo)
                {
                    Text = unitNo
                };
                //1.创建TextBox关联到page上
                TextBox textBox = CreateTextControl(unitNo);
                page.Controls.Add(textBox);
                ServoTab.TabPages.Add(page);
            }
            catch (Exception ex)
            {
                MessageBox.Show("数据库连接异常!请检查连接配置!causeBy:" + ex.Message);
                Environment.Exit(Environment.ExitCode);
                Dispose();
                Close();
            }
        }
        #endregion

        #region ###生成组件###
        private TextBox CreateTextControl(string name)
        {
            FontFamily fontFamily = new FontFamily("楷体");
            TextBox tb = new TextBox
            {
                Name = name,
                Multiline = true,
                BorderStyle = BorderStyle.None,
                Dock = DockStyle.Fill,
                ScrollBars = ScrollBars.Both,
                Font = new Font(fontFamily, 9.0f)
            };
            show_dict.Add(name, tb);
            return tb;
        }
        #endregion

        private void FrmMain_Load(object sender, EventArgs e)
        {
            //开启监听(由unit_no决定)
            if (GlobalCachePool.single_unit_dict.TryGetValue("HK_CV", out PlcUnitEntity s7Unit))
            {
                string unitNo = s7Unit.UNIT_NO;
                //此处直接开启设备连接
                S7NetClient s7Client = new S7NetClient(unitNo, s7Unit.HOST, s7Unit.PORT);
                s7Client.Start();
                GlobalCachePool.s7_clinet.Add(unitNo, s7Client);

                //装载需要监听的PLC_ITEM
                string itemSql = "select * from plc_item where unit_no='HK_CV'";
                string eventSql = "select * from plc_event where belong_sys='HK_CV'";
                try
                {
                    List<PlcItemEntity> items = DBFactory.QueryList<PlcItemEntity>(itemSql);
                    if (items == null || items.Count == 0)
                    {
                        ShowMsgUpdate(unitNo, "ERROR", "未检测到需要监听的PLC_ITEM");
                        return;
                    }
                    GlobalCachePool.plcItems_dict.Add("HK_CV", items);

                    //装载相关事件
                    List<PlcEventEntity> events = DBFactory.QueryList<PlcEventEntity>(eventSql);
                    if (events != null && events.Count > 0)
                    {
                        GlobalCachePool.plcEvents_dict.Add("HK_CV", events);
                        foreach (PlcEventEntity eva in events)
                        {
                            ShowMsgUpdate(unitNo, "0", $"装载事件{eva.EVENT_NO}!");
                            ServoUtils.InitPlcEvent(eva);
                        }
                    }

                    //将信号点与事件进行关联
                    foreach (PlcItemEntity item in items)
                    {
                        ShowMsgUpdate(unitNo, "0", $"装载信号点{item.ITEM_NO}!");
                        ServoUtils.InitPlcItem(item);
                    }
                    WriteHandler writeHandler = new WriteHandler(unitNo);
                    writeHandler.ShowMessageUpdated += ShowMsgUpdate;
                    JudgeHandler judgeHandler = new JudgeHandler(unitNo, writeHandler);
                    judgeHandler.ShowMessageUpdated += ShowMsgUpdate;
                    InitLoading initLoading = new InitLoading(unitNo, judgeHandler);
                    initLoading.ShowMessageUpdated += ShowMsgUpdate;
                    ThreadPool.QueueUserWorkItem(obj =>
                    {
                        initLoading.CircleListening();
                    });

                    //开启一个线程用于监听是否有人工修改点信号值的操作
                    ThreadPool.QueueUserWorkItem(obj =>
                    {
                        while (true)
                        {
                            //ShowMsgUpdate(unitNo, "0", "监听信号点是否修改!");
                            initLoading.InitListenChange();
                            Thread.Sleep(1000);
                        }
                    });

                    ShowMsgUpdate(unitNo, "0", "海康工作站伺服程序启动成功!信号监听中...");
                }
                catch (Exception)
                {
                    ShowMsgUpdate(unitNo, "ERROR", "数据库访问异常!请检查连接配置");
                    return;
                }
            }
        }

        private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            DialogResult result = MessageBox.Show("确定要关闭伺服程序？", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

            if (result == DialogResult.No)
            {
                e.Cancel = true;
            }
            else
            {
                Environment.Exit(Environment.ExitCode);
                Dispose();
                Close();
            }
        }

        #region ###信息展示###
        private void ShowMsgUpdate(string unitNo, string code, string msg)
        {
            //通过设备名称找到属于自己的TextBox
            if (show_dict.TryGetValue(unitNo, out TextBox showBox))
            {
                //使用委托的方式调用控件
                showBox.Invoke(new Action(() =>
                {
                    showBox.AppendText($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} >>> {code} {msg}\r\n");
                }));
            }
        }
        #endregion
    }
}
